﻿#pragma once
#include "Logger.h"
#include <QObject>
#include <QtNetwork>
static const QString g_UserAgent[] = {
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0",
    "Opera/8.0 (Windows NT 5.1; U; en)",
    "Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50",
    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"};
class Spyder : public QObject
{
    Q_OBJECT
public:
    explicit Spyder(QObject* parent = nullptr)
        : QObject(parent)
    {
        connect(&m_networkManager, &QNetworkAccessManager::finished, this, &Spyder::HandleFinish);
    }
    void StartCrawling(const QSet<QUrl>& urls)
    {
        m_urls = urls;
        CrawNextUrl();
    }
signals:
    void CrawlingFinished();

protected:
    virtual QVector<QString> Decode(const QByteArray& data)      = 0;
    virtual void             DealWithInfo(QVector<QString> info) = 0;
private slots:
    void HandleFinish(QNetworkReply* reply)
    {
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray data       = reply->readAll();
            QString    htmlConent = QString::fromUtf8(data);
            DealWithInfo(Decode(data));
        }
        else {
            int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            HandleError(reply);
        }
        reply->deleteLater();
        //处理下一条请求
        CrawNextUrl();
    }

private:
    void HandleError(QNetworkReply* reply)
    {
        if (!reply) { return; }
        Logger::GetInstance().LogError(reply->errorString());
    }
    void CrawNextUrl()
    {
        if (!m_urls.isEmpty()) {
            QUrl url = *m_urls.begin();
            m_urls.erase(m_urls.begin());
            Logger::GetInstance().LogInfo("crawling url: " + url.toString());
            QNetworkRequest request(url);

            request.setHeader(QNetworkRequest::UserAgentHeader, g_UserAgent[0]);
            m_networkManager.get(request);
        }
        //
        else {
            emit CrawlingFinished();
        }
    }

private:
    QNetworkAccessManager m_networkManager;
    QSet<QUrl>            m_urls;
};